package by.yakusekmaxim.bookgid.dataaccess.impl;

import java.util.List;

import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.SingularAttribute;

import org.hibernate.jpa.criteria.OrderImpl;
import org.springframework.stereotype.Repository;

import by.yakusekmaxim.bookgid.dataaccess.UserAccount2BookDao;
import by.yakusekmaxim.bookgid.dataaccess.util.Filter;
import by.yakusekmaxim.bookgid.datamodel.Book;
import by.yakusekmaxim.bookgid.datamodel.UserAccount;
import by.yakusekmaxim.bookgid.datamodel.UserAccount2Book;
import by.yakusekmaxim.bookgid.datamodel.UserAccount2Book_;

@Repository
public class UserAccount2BookDaoImpl extends
		AbstractDaoImpl<Long, UserAccount2Book> implements UserAccount2BookDao {

	protected UserAccount2BookDaoImpl() {
		super(UserAccount2Book.class);
	}

	@Override
	public List<UserAccount2Book> getUserAccount2BookDao(Book book,
			UserAccount user) {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<UserAccount2Book> criteria = cBuilder
				.createQuery(UserAccount2Book.class);
		Root<UserAccount2Book> root = criteria.from(UserAccount2Book.class);
		criteria.where(cBuilder.equal(root.get(UserAccount2Book_.book), book),
				cBuilder.equal(root.get(UserAccount2Book_.userAccount), user));
		criteria.select(root);

		TypedQuery<UserAccount2Book> query = getEm().createQuery(criteria);
		List<UserAccount2Book> results = query.getResultList();
		return results;
	}

	@Override
	public List<UserAccount2Book> getAllUserAccount2BookDao(
			SingularAttribute<UserAccount2Book, ?> attribute,
			boolean ascending, int startRecord, int pageSize, UserAccount user) {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<UserAccount2Book> criteria = cBuilder
				.createQuery(UserAccount2Book.class);
		Root<UserAccount2Book> root = criteria.from(UserAccount2Book.class);
		criteria.where(cBuilder.equal(root.get(UserAccount2Book_.userAccount),
				user));
		criteria.select(root);
		criteria.orderBy(new OrderImpl(root.get(attribute), ascending));

		TypedQuery<UserAccount2Book> query = getEm().createQuery(criteria);
		query.setFirstResult(startRecord);
		query.setMaxResults(pageSize);

		List<UserAccount2Book> results = query.getResultList();
		return results;
	}

	@Override
	public List<UserAccount2Book> getAllUserAccount2BookDao(
			SingularAttribute<UserAccount2Book, ?> attribute,
			boolean ascending, int startRecord, int pageSize,
			Filter<UserAccount2Book> filter, UserAccount user) {
		SingularAttribute<UserAccount2Book, ?> attributeF = filter
				.getAttribute();
		Object valueF = filter.getValue();

		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<UserAccount2Book> criteria = cBuilder
				.createQuery(UserAccount2Book.class);
		Root<UserAccount2Book> root = criteria.from(UserAccount2Book.class);
		criteria.where(cBuilder.equal(root.get(attributeF), valueF),
				cBuilder.equal(root.get(UserAccount2Book_.userAccount), user));
		criteria.select(root);
		criteria.orderBy(new OrderImpl(root.get(attribute), ascending));

		TypedQuery<UserAccount2Book> query = getEm().createQuery(criteria);
		query.setFirstResult(startRecord);
		query.setMaxResults(pageSize);

		List<UserAccount2Book> results = query.getResultList();
		return results;
	}

	@Override
	public Long getCountByUserAccount(UserAccount user) {
		
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<Long> criteria = cBuilder.createQuery(Long.class);
		Root<UserAccount2Book> root = criteria.from(UserAccount2Book.class);
		criteria.where(cBuilder.equal(root.get(UserAccount2Book_.userAccount), user));
		criteria.select(cBuilder.count(root));

		TypedQuery<Long> query = getEm().createQuery(criteria);
		return query.getSingleResult();
	}

	@Override
	public Long getCountByUserAccount(Filter<UserAccount2Book> filter,
			UserAccount user) {
		SingularAttribute<UserAccount2Book, ?> attributeF = filter.getAttribute();
		Object valueF = filter.getValue();
		System.out.println(valueF.toString());
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<Long> criteria = cBuilder.createQuery(Long.class);
		Root<UserAccount2Book> root = criteria.from(UserAccount2Book.class);
		criteria.where(cBuilder.equal(root.get(UserAccount2Book_.userAccount), user),
				cBuilder.equal(root.get(attributeF), valueF));
		criteria.select(cBuilder.count(root));

		TypedQuery<Long> query = getEm().createQuery(criteria);
		return query.getSingleResult();
	}

	@Override
	public Long getCountByBook(Filter<UserAccount2Book> filter, Book book) {
		SingularAttribute<UserAccount2Book, ?> attributeF = filter.getAttribute();
		Object valueF = filter.getValue();
		
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<Long> criteria = cBuilder.createQuery(Long.class);
		Root<UserAccount2Book> root = criteria.from(UserAccount2Book.class);
		criteria.where(cBuilder.equal(root.get(UserAccount2Book_.book), book),
				cBuilder.equal(root.get(attributeF), valueF));
		criteria.select(cBuilder.count(root));

		TypedQuery<Long> query = getEm().createQuery(criteria);
		return query.getSingleResult();
	}
}
